<?php

class CW_ValidatorClass {

	private $input;
	private $tests;
	private $errors;

	public function __construct($input)
	{
		$this->input = $input;
		$this->tests = array();
		$this->errors = array();
	}

	public function getErrors()
	{
		return $this->errors;
	}

	public function getFieldValues()
	{
		return $this->input;
	}

	public function addTest($field, $rules, $error)
	{
		$this->tests[$field] = array('field' => $field, 'rules' => $rules, 'error' => $error);

		return true;
	}

	public function runTests()
	{
		if(false == $this->tests)
		{
			return true;
		}

		$all_passed = true;

		foreach($this->tests as $field => $test)
		{
			if(false == $this->runSingleTest($field, $test['rules'], $test['error']))
			{
				$all_passed = false;

				$this->errors[$field] = $test['error'];
			}
		}

		return $all_passed;
	}

	private function runSingleTest($field, $rules, $error)
	{
		if(false == isset($this->input[$field]))
		{
			throw new CoreException("Validation of field '{$field}' failed. That field does not exist.");
		}

		if(false == $rules)
		{
			throw new CoreException("Validation of field '{$field}' failed. No validation rules have been defined!");
		}

		foreach($rules as $rule)
		{
			$test_passed = true;
			$param = null;

			if(preg_match('#^([a-z-]+)\((.*?)\)$#i', $rule, $match))
			{
				$rule  = $match[1];
				$param = $match[2];
			}

			switch($rule)
			{
				case 'prep':

					$test_passed = $this->testPrep($this->input[$field], $param, $field);
					break;

				case 'pattern':

					$test_passed = $this->testPattern($this->input[$field], $param);
					break;

				case 'required':

					$test_passed = $this->testRequired($this->input[$field]);
					break;

				case 'matches':

					$test_passed = $this->testMatches($this->input[$field], $param);
					break;

				case 'exact-length':

					$test_passed = $this->testExactLength($this->input[$field], $param);
					break;

				case 'alpha':

					$test_passed = $this->testAlpha($this->input[$field]);
					break;

				case 'alpha-numeric':

					$test_passed = $this->testAlphaNumeric($this->input[$field]);
					break;

				case 'alpha-numeric-dashes':

					$test_passed = $this->testAlphaNumericDashes($this->input[$field]);
					break;

				case 'numeric':

					$test_passed = $this->testNumeric($this->input[$field]);
					break;

				case 'integer':

					$test_passed = $this->testInteger($this->input[$field]);
					break;

				case 'is-email':

					$test_passed = $this->testEmailAddress($this->input[$field]);
					break;

				case 'bool':

					$test_passed = $this->testBoolean($this->input[$field]);
					break;

				case 'min-string-length':

					$test_passed = $this->testMinLength($this->input[$field], $param);
					break;

				case 'max-string-length':

					$test_passed = $this->testMaxLength($this->input[$field], $param);
					break;

				default:

					throw new CoreException("Validation of field '{$field}' failed. Rule '{$rule}' is not defined!");
					break;
			}

			if(false == $test_passed)
			{
				return false;
			}
		}

		return $test_passed;
	}

	private function testPrep($string, $parameter, $field)
	{
		if(false == function_exists($parameter))
		{
			throw new CoreException("Could not prep field '{$field}' with function '{$parameter}'. This function does not exist.");
		}

		if(false == isset($this->input[$field]))
		{
			return $string;
		}

		$this->input[$field] = $parameter($string);

		return true;
	}

	private function testPattern($string, $parameter)
	{
		if(false == $parameter)
		{
			return false;
		}

		return preg_match($parameter, $string);
	}

	private function testMatches($string, $parameter)
	{
		if(false == isset($this->input[$parameter]))
		{
			return false;
		}

		return (trim($string) == trim($this->input[$parameter])) ? true : false;
	}

	private function testExactLength($string, $parameter)
	{
		return (strlen($string) == $paramter) ? false : true;;
	}

	private function testAlpha($string)
	{
		return preg_match('#^[a-z]$#i', $string);
	}

	private function testAlphaNumeric($string)
	{
		return preg_match('#^[a-z0-9]$#i', $string);
	}

	private function testAlphaNumericDashes($string)
	{
		return preg_match('#^[a-z0-9-_]$#i', $string);
	}

	private function testEmailAddress($string)
	{
		return preg_match("#^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$#i", $string);
	}

	private function testNumeric($string)
	{
		return preg_match('#^[0-9]$#', $string);
	}

	private function testInteger($string)
	{
		return is_int($string);
	}

	private function testBoolean($string)
	{
		return is_bool($string);
	}

	private function testRequired($string)
	{
		return trim($string) ? true : false;
	}

	private function testMinLength($string, $parameter)
	{
		return (strlen($string) >= $parameter) ? true : false;
	}

	private function testMaxLength($string, $parameter)
	{
		return (strlen($string) <= $parameter) ? true : false;
	}
}

?>